Alexa 开发新技能 - python flask

非常简单的教程,讲怎么给 Alexa 添加新的 skill,让你的 Echo 更个性化。本篇添加的 skill 是让 Alexa 从 reddit 上读前 10 条热点。

代码戳Alexa-Starter-RedditReader,其他版本如用 Lambda Function 实现,见Alexa 开发新技能 - Lambda

Requirements

Code for new skill

这里我们用 Flask 来建一个简单的 web application,代码如下,get_headlines() 是我们主要的 method,从 Reddit 里返回 10 条热点。逻辑是这样的:

  • (用户呼唤 Reddit Reader)
  • Alexa 问用户 ‘Hello there, would you like the news?’
  • 用户回答
    肯定回复: 读 10 headlines
    否定回复: 回答 ‘I am not sure why you asked me to run then, but okay… bye’

注意要确保有上面的 python package,如果没有,先安装

  • flask == 0.12.1
  • flask_ask == 0.9.3
  • unidecode == 0.4.20
1
2
3
$ pip install flask
$ pip install flask_ask
$ pip install unidecode

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
from flask import Flask, render_template
from flask_ask import Ask, statement, question, session
import json
import requests
import time
import unidecode
# define Flask app
app = Flask(__name__)
# give basic endpoint, can be flask skill/program endpoint
ask = Ask(app, "/reddit_reader")
def get_headlines():
sess = requests.Session()
# just change user-agent
sess.headers.update({'User-Agent': 'I am testing Alexa'})
time.sleep(1)
# get first 10 headlines
url = 'https://reddit.com/r/worldnews/.json?limit=10'
html = sess.get(url)
data = json.loads(html.content.decode('utf-8'))
titles = [unidecode.unidecode(listing['data']['title']) for listing in data['data']['children']]
titles = '...'.join([i for i in titles])
return titles
# set home url path
@app.route('/')
def homepage():
return 'hi there, how ya doin?'
@ask.launch
def start_skill():
# it will say
welcome_message = 'Hello there, would you like the news?'
# question expect response
return question(welcome_message)
# handle user input yes or no response
# user input is intent
@ask.intent("YesIntent")
def share_headlines():
# grab the headline
headlines = get_headlines()
headline_msg = 'The current world news headlines are {}'.format(headlines)
# statement tell you sth
return statement(headline_msg)
@ask.intent("NoIntent")
def no_intent():
bye_text = 'I am not sure why you asked me to run then, but okay... bye'
return statement(bye_text)
if __name__ == '__main__':
app.run(debug=True)

Set endpoint

这里我们用 ngrok,将本地 web 服务部署到公共网络。如果没有下载,先从下载并解压,然后运行,端口就是 Flask 运行的端口

1
$ ./ngrok http 5000

Deploy

Amazon developer 网站上注册用户并登陆,注意这里的用户名和你的 Echo 用户名是一致的。点开 Alexa tab,选择 add skill,开始部署。

Step1:
填写 Name 和 Invocation Name,Invocation Name 用来 invoke app
1.jpg

Step2:
主要填写 Intent Schema 和 Sample Utterances

Intent Schema: how alexa will traverse your application

1
2
3
{ "intents": [{ "intent": "YesIntent" },
{ "intent": "NoIntent" }]
}

Sample Utterances: the words people say to trigger intent

1
2
3
4
5
YesIntent yes
YesIntent sure
NoIntent no
NoIntent go away

2.jpg 3.jpg

Step3:
选择并填写 Endpoint,这里我们用的是 HTTPS,可以在 ngrok 的命令行找到 endpoint url
6.jpg
4.jpg

Step4:
这里我们就选 My development endpoint is a sub-domain of a domain that has a wildcard certificate from a certificate authority,作为测试的话不选也没有关系
5.jpg

Step5:
就可以用 Echo 来 test 啦~ 如果没有 Echo,可以用 Service Simulator 来模拟
先给 Alexa 一个关于 Reddit Reader 的指令,然后按照我们的代码,Alexa 会问你要不要读新闻

7.jpg

然后我们回答 yes,Alexa 就开始读新闻啦~
8.jpg

一个简单的实例PNC_Virtual_Assistant

参考链接
Intro and Skill Logic - Alexa Skills w/ Python and Flask-Ask Part 1
Flask Building Responses

徐阿衡 wechat
欢迎关注:徐阿衡的微信公众号
客官,打个赏呗~